package com.apobates.forum.thrones.controller.helper;

import com.apobates.forum.thrones.vo.TokenMoldBean;
import com.apobates.forum.utils.Commons;
import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
import java.util.TreeMap;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;

/**
 * 为请求增加token参数
 *
 * @author xiaofanku
 * @since 20200525
 */
public class RequestTokenParameterFilter implements Filter {
    private final static Logger logger = LoggerFactory.getLogger(RequestTokenParameterFilter.class);
    @Value("${site.domain}")
    private String sitedomain;
    private final static String TS = "token";
    
    public RequestTokenParameterFilter() {
        logger.info("[RTP]init no arg");
    }
    
    public RequestTokenParameterFilter(String sitedomain) {
        logger.info("[RTP]init inject arg: " + sitedomain);
        this.sitedomain = sitedomain;
    }
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.sitedomain = filterConfig.getInitParameter("sitedomain");
        logger.info("[RTP]RequestTokenParameterFilter init(" + sitedomain + ")");
    }
    
    @Override
    public void destroy() {
        logger.info("[RTP]RequestTokenParameterFilter destroy");
    }
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        logger.info("[RTP][1]inside doFilter value:" + sitedomain);
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        /* Getting actual Redirect Param Value */
        String requestURI = httpServletRequest.getRequestURI();
        //不处理的资源
        if (!isProcessed(requestURI)) {
            chain.doFilter(request, response);
            return;
        }
        //若请求参数中含有token,直接退出不再增补token
        if (null != httpServletRequest.getParameter("token") && Commons.isNotBlank(httpServletRequest.getParameter("token"))) {
            chain.doFilter(request, response);
            return;
        }
        logger.info("[RTP][2]processed URI:" + requestURI);
        TokenMoldBean tmb = makeToken(httpServletRequest);
        if (!tmb.isInherit()) { //只有新生的才放到session中
            httpServletRequest.getSession().setAttribute(TS, tmb.getToken());
        }
        /*
        * Modifying redirect param value and also adding new parameter to
        * request object
        */
        Map<String, String[]> modifyAddParamValueMap = new TreeMap<>();
        String[] tokenParamArray = new String[1];
        tokenParamArray[0] = tmb.getToken();
        modifyAddParamValueMap.put(TS, tokenParamArray);
        // @20200501
        //String[] mlcParamArray = new String[1];
        //mlcParamArray[0] = tmb.getToken();
        //modifyAddParamValueMap.put("mlc", mlcParamArray);
        //
        HttpServletRequest wrappedRequest = new EnhancedHttpRequest(httpServletRequest, modifyAddParamValueMap);
        chain.doFilter(wrappedRequest, response);
    }
    
    // 是否是本地请求
    private boolean isLocalRequest(String httpReferer) {
        // 包含http://
        // 是否是本站地址
        if (null == sitedomain) {
            return false;
        }
        if (httpReferer.startsWith(sitedomain)) {
            return true;
        }
        return false;
    }
    //是否对资源进行处理
    private boolean isProcessed(String requestURI) {
        if (requestURI.startsWith("/static")) {
            return false;
        }
        //后缀也不处理
        String fe = Commons.getFileExtension(requestURI);
        if (null != fe && fe.length() > 0) {
            return !Arrays.asList("js", "png", "css", "jpg", "ico", "jpeg", "svg", "html", "gif", "xml", "rss").contains(fe.toLowerCase());
        }
        return true;
    }
    
    private TokenMoldBean makeToken(HttpServletRequest request) {
        String token = Commons.randomAlphaNumeric(8);
        // 来源页
        String httpReferer = request.getHeader("referer");
        // 没有->
        if (null == httpReferer) {
            return new TokenMoldBean(token);
        }
        boolean isLocal = isLocalRequest(httpReferer);
        if (!isLocal) { // 来源非本站域名->
            return new TokenMoldBean(token);
        } else { // 是本站->
            // 从session|cookie中取
            Object sessionObj = request.getSession().getAttribute(TS);
            return (null == sessionObj) ? new TokenMoldBean(token) : new TokenMoldBean(sessionObj.toString(), true);
        }
    }
}